package lg.minecraft.plugin.library.config;

import lg.minecraft.plugin.library.LGPlugin;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author langle__
 * @version 1.0
 */
public class LGConfig extends LGBaseConfig {

    public LGConfig(LGPlugin plugin, String name) {
        super(plugin, name);
    }

    @Override
    public void saveDefault(String resourcePath, boolean replace) {
        if (file.exists() && !replace) return;
        this.save();
    }

    @Override
    public void save() {
        List<Field> fields = getAllFields(this.getClass());

        for (Field field : fields) {
            if (!field.isAnnotationPresent(ConfigurationField.class)) continue;
            field.setAccessible(true);
            String valueName = field.getAnnotation(ConfigurationField.class).value();
            try {
                Object object = field.get(this);
                this.set(valueName, object);
            } catch (Exception e) {
                plugin.getLogger().warning("无法获取 " + field.getName() + " 的值");
            }
        }

        super.save();
    }

    @Override
    public void load() {
        super.load();

        List<Field> fields = getAllFields(this.getClass());

        for (Field field : fields) {
            if (!field.isAnnotationPresent(ConfigurationField.class)) continue;
            field.setAccessible(true);
            String valueName = field.getAnnotation(ConfigurationField.class).value();
            try {
                Object target = field.get(this);
                Object object = this.get(valueName, target);
                if (object != null && target.getClass() != object.getClass()) {
                    object = convertObjectToTargetType(object, target);
                }
                field.set(this, object);
            } catch (Exception e) {
                plugin.getLogger().warning("无法设置 " + field.getName() + " 的值");
            }
        }

    }

    private Object convertObjectToTargetType(Object object, Object target) {
        if (object.getClass() == Integer.class) {
            Class<?> clazz = target.getClass();
            if (clazz == Byte.class) {
                return ((Integer) object).byteValue();
            } else if (clazz == Short.class) {
                return ((Integer) object).shortValue();
            } else if (clazz == Long.class) {
                return ((Integer) object).longValue();
            }
        } else if (object.getClass() == Double.class) {
            Class<?> clazz = target.getClass();
            if (clazz == Float.class) {
                return ((Double) object).floatValue();
            }
        } else if (object.getClass() == String.class) {
            Class<?> clazz = target.getClass();
            if (clazz == Character.class) {
                String str = (String) object;
                if (str.length() == 1) {
                    return str.charAt(0);
                } else {
                    throw new IllegalArgumentException("String length must be 1 to convert to Character");
                }
            }
        } else if (target.getClass().isArray() && target.getClass().getComponentType() == String.class) {
            Class<?> clazz = object.getClass();
            if (clazz == ArrayList.class) {
                ArrayList<?> arrayList = (ArrayList<?>) object;
                if (!arrayList.isEmpty() && arrayList.get(0) instanceof String) {
                    return arrayList.toArray(new Object[0]);
                } else {
                    throw new IllegalArgumentException("ArrayList does not contain String elements");
                }
            }
        }
        return target;
    }

    protected List<Field> getAllFields(Class<?> clazz) {
        List<Field> fieldList = new ArrayList<>();
        while (clazz != null) {
            fieldList.addAll(Arrays.asList(clazz.getDeclaredFields()));
            clazz = clazz.getSuperclass();
        }
        return fieldList;
    }

}
